﻿(function mementoDefinition(global) {
    global.CanvasState = global.CanvasState || {};

    ///Memento
    CanvasState.memento = function (state) {
        this._state = state;
    };
    Object.defineProperty(CanvasState.memento.prototype, "state", {
        get: function () { return this._state; }
    });

    ///Caretaker constructor
    CanvasState.caretaker = function (maxLevels) {
        this._undoStates = [];
        this._redoStates = [];
        this._maxLevels = maxLevels;
    };

    CanvasState.caretaker.prototype.addMemento = function (memento) {
        this._undoStates.push(memento);
        this._redoStates = [];
        if (this._undoStates.length > this._maxLevels) {
            this._undoStates.splice(0, 1);
        }
    };

    CanvasState.caretaker.prototype._canUndo = function () {
        return this._undoStates.length > 1;
    }
    CanvasState.caretaker.prototype._canRedo = function () {
        return this._redoStates.length > 0;
    }

    CanvasState.caretaker.prototype.getUndoMemento = function () {
        if (this._canUndo()) {
            var state = this._undoStates.pop();
            this._redoStates.push(state);
            return this._undoStates[this._undoStates.length - 1];
        }
        else
            throw "Undo not allowed, states array empty";
    };
    CanvasState.caretaker.prototype.getRedoMemento = function () {
        if (this._canRedo()) {
            var state = this._redoStates.pop();
            this._undoStates.push(state);
            return state;
        }
        else
            throw "Redo not allowed, states array empty";
    }

    Object.defineProperty(CanvasState.caretaker.prototype, "canUndo", {
        get: function () { return this._canUndo(); }
    });
    Object.defineProperty(CanvasState.caretaker.prototype, "canRedo", {
        get: function () { return this._canRedo(); }
    });


    ///Originator
    CanvasState.originator = function (canvas) {
        this._canvas = canvas;
        this._ctx = canvas.getContext("2d");
    };
    CanvasState.originator.prototype.saveToMemento = function (x, y, w, h) {
        if (x === undefined)
            x = 0;
        if (y === undefined)
            y = 0;
        if (w === undefined)
            w = this._canvas.width;
        if (h === undefined)
            h = this._canvas.height;

        var img = this._ctx.getImageData(x, y, w, h);
        return new CanvasState.memento({ image: img, x: x, y: y, w: w, h: h });
    };
    CanvasState.originator.prototype.restoreFromMemento = function (memento) {
        this._ctx.putImageData(memento.state.image, memento.state.x, memento.state.y);
    };

})(this);

